﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Server
{
    public partial class FrmMain : Form
    {
        public const int PORT = 12345;

        private Lib.Server server;

        public FrmMain()
        {
            InitializeComponent();
        }

        private void WriteLog(string str)
        {
            this.Invoke(new Action(() =>
            { LstLog.Items.Add(str); }));
        }

        private void FrmMain_Load(object sender, EventArgs e)
        {

        }

        private void BtnStartServer_Click(object sender, EventArgs e)
        {
            if (BtnStartServer.Tag == null)
            {
                WriteLog("Starting server on port: " + PORT);
                if (server != null) server.Close();

                server = new Lib.Server(PORT);

                server.OnError = OnError;
                server.OnAccept = OnAccept;
                server.OnReceive = OnReceive;

                server.Listen();
                BtnStartServer.Tag = "Stop";
                BtnStartServer.Text = "Stop server";

                WriteLog("Server is started");
            }
            else
            {
                if (server != null)
                {
                    server.Close();
                    server = null;
                }
                BtnStartServer.Text = "Start server";
                BtnStartServer.Tag = null;
            }
        }

        private void ReloadClientList()
        {
            this.Invoke(new Action(() =>
            {
                LstClients.Items.Clear();

                foreach (var item in Lib.ClientInfo.GetInstance().ClientList)
                {
                    var c = item.Value;
                    if (!c.UserName.Equals(""))
                    {
                        ListViewItem lvi = new ListViewItem(c.UserName);
                        lvi.SubItems.Add(new ListViewItem.ListViewSubItem(lvi, c.Socket.RemoteEndPoint.ToString()));
                        LstClients.Items.Add(lvi);
                    }
                }
            }));
        }

        #region Handling event
        private void OnError(string func, string str)
        {
            WriteLog("Error on \"" + func + "\": " + str);
        }

        private Lib.ClientInfo OnAccept(Socket socket)
        {
            Lib.ClientInfo client = new Lib.ClientInfo();
            client.Socket = socket;
            Lib.ClientInfo.GetInstance().AddClient(client);

            WriteLog("Client \"" + socket.RemoteEndPoint.ToString() + "\" has just connected");
            return client;

        }

        private Lib.ClientInfo OnReceive(Socket socket, int len)
        {
            Lib.ClientInfo c = Lib.ClientInfo.GetInstance().GetClientBySock(socket);
            
            if (c != null)
            {
                byte[] data = c.Buffer.Take(len).ToArray();

                if (c.UserName.Equals("")) // Username
                {
                    string username = Lib.Helpper.GetString(data);
                    c.UserName = username;
                    server.ResponseOk(socket);

                    ReloadClientList();

                    WriteLog("Client \"" + c.Socket.RemoteEndPoint.ToString() + "\" is know as \"" + username + "\"");
                }
                else // Messenger or command
                {
                    string content = Lib.Helpper.GetString(data);
                    if (content.Equals("<~~~>")) {
                        server.SendListOfUsers(socket);
                    }
                    else
                    {
                        int idx = 0;
                        for (int i = 0; i < content.Length; ++i)
                        {
                            if (content[i] == ':')
                            {
                                idx = i;
                                break;
                            }
                        }

                        string un = content.Substring(0, idx);
                        string ms = content.Substring(idx + 1);
                        server.SendMessage(un, ms);
                        server.ResponseOk(socket);
                    }
                }

                return c;
            }

            return null;
        }
        #endregion
    }
}
